package wangwenjun.phase2.concurrencypattern.balking;

import lombok.extern.slf4j.Slf4j;
import util.ThreadUtil;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ChangLiang
 * @date 2020/6/16
 */
@Slf4j
public class Document {

    /**
     * changed 是balking pattern 关注的状态
     */
    private boolean changed = false;

    /**
     * 一次需要保存的内容 可以将其理解为内容缓存
     */
    private List<String> contentList = new ArrayList<>();

    private final FileWriter writer;

    private Document(String documentPath, String documentName) throws IOException {
        this.writer = new FileWriter(new File(documentPath, documentName));
    }

    private static AutoSaveThread autoSaveThread;

    public static Document create(String documentPath, String documentName) throws IOException {
        Document document = new Document(documentPath, documentName);
        autoSaveThread = new AutoSaveThread(document);
        autoSaveThread.start();
        return document;
    }

    /**
     * edit方法和save方法同步 目的在于防止当文档在保存的过程中如果遇到新的内容被编辑时引起的共享资源冲突问题
     *
     */

    public void edit(String content) {
        synchronized (this) {
            this.contentList.add(content);
            this.changed = true;
        }
    }

    public void save() throws IOException {
        synchronized (this) {
            // balking pattern
            if (!changed) {
                return;
            }
            log.info("Thread: {} execute the save action", Thread.currentThread());
            contentList.forEach(line->{
                try {
                    this.writer.write(line);
                    this.writer.write("\r\n");
                } catch (IOException e) {
                    ThreadUtil.exceptionToString(e);
                }
            });

            writer.flush();
            this.changed = false;
            this.contentList.clear();
        }
    }

    public void close() throws IOException {
        autoSaveThread.interrupt();
        writer.close();
    }
}
